iT邦幫忙

2022 iThome 鐵人賽

DAY 24
0
Web 3

當 APP develop 遇上 web3 與 Metaverse 浪潮 系列 第 24

[Day 貳拾肆] 來開發元宇宙中藥鋪吧12 - 如何處理場景切換焦點與旋轉置焦點物間

  • 分享至 

  • xImage
  •  

我們這邊將改寫原本 本系列第10篇中使用的 <bounds/>

參考

https://github.com/pmndrs/drei#bounds

function Foo() {
  const bounds = useBounds()
  useEffect(() => {
    // Calculate scene bounds
    bounds.refresh().clip().fit()
    // Or, focus a specific object or box3
    // bounds.refresh(ref.current).clip().fit()
    // bounds.refresh(new THREE.Box3()).clip().fit()

<Bounds>
  <Foo />

建立另外兩個目標物後

圖很大你要忍一下

import * as THREE from 'three'
import React, { useRef, Suspense, useState } from 'react'
import { Canvas, useFrame, useThree } from '@react-three/fiber'
import { OrbitControls, Bounds, useBounds, BakeShadows, Environment, ContactShadows, Cloud, Sky } from '@react-three/drei'

import { Room } from './Room'
import ModelDraco from './ModelDracoOG'
import GoldenText from './GoldenText'
import ModelCupboard from './Model/ModelCupboard'
import ModelWall from './Model/ModelWall'
import ModelCMD from './ModelCMD'
import { OmitProps } from 'antd/lib/transfer/ListBody'

function Rig() {
  const camera = useThree((state) => state.camera)
  const vec = new THREE.Vector3()
  return useFrame((state) => {
    // camera.position.x = Math.sin(state.clock.elapsedTime) * 20
    // camera.position.z = Math.sin(state.clock.elapsedTime) * 20
    // camera.position.z = state.clock.elapsedTime * 10
    // const ref = useRef()
    // useFrame(() => {
    // camera.position(vec.set(10, 2000, 10), 0.05)
    // camera.position.lerp(vec.set(10, 2000, 10), 0.05)
    // camera.position.lerp(vec.set(10, 1050, 10), vec.set(10, 50, 10), 0.05)

    //   ref.current.position.lerp(vec.set(mouse.x * 1, mouse.y * 0.1, 0), 0.1)
    //   ref.current.rotation.y = THREE.MathUtils.lerp(ref.current.rotation.y, (-mouse.x * Math.PI) / 20, 0.1)
    // })
    camera.position
  })
}

export default function App({ ready }) {
  const [clicked_to_Left, click_to_Left] = useState(false)
  const [clicked_to_Right, click_to_Right] = useState(false)
  const ref_zero = useRef()
  const ref_Left = useRef()

  return (
    <Canvas orthographic shadows dpr={[1, 2]} camera={{ position: [10, 10, 10], zoom: 10 }}>
      <Rig />
      <Sky azimuth={0.1} turbidity={10} rayleigh={0.5} inclination={0.6} distance={1000} />

      {/* <color attach="background" args={['#252530']} /> */}
      {/* <color attach="background" args={['#252530']} /> */}
      <color attach="background" args={['#FCF4EE']} />
      {/* <color attach="background" args={['#E34234']} /> */}
      <Environment preset="city" />
      <Suspense fallback={null}>
        <group scale={5} position={[5, 100, 0]}>
          <Cloud position={[-4, -2, -25]} speed={0.2} opacity={1} />
          <Cloud position={[4, 2, -15]} speed={0.2} opacity={0.5} />
          <Cloud position={[-4, 2, -10]} speed={0.2} opacity={1} />
          <Cloud position={[4, -2, -5]} speed={0.2} opacity={0.5} />
          <Cloud position={[4, 2, 0]} speed={0.2} opacity={0.75} />
        </group>
        <group position={[0, 10, 0]}>
          <Cloud position={[-4, -2, -25]} speed={0.2} opacity={1} />
          <Cloud position={[4, 2, -15]} speed={0.2} opacity={0.5} />
          <Cloud position={[-4, 2, -10]} speed={0.2} opacity={1} />
          <Cloud position={[4, -2, -5]} speed={0.2} opacity={0.5} />
          <Cloud position={[4, 2, 0]} speed={0.2} opacity={0.75} />
        </group>
        <group position={[10, 10, 0]}>
          <Cloud position={[-4, -2, -25]} speed={0.2} opacity={1} />
          <Cloud position={[4, 2, -15]} speed={0.2} opacity={0.5} />
          <Cloud position={[-4, 2, -10]} speed={0.2} opacity={1} />
          <Cloud position={[4, -2, -5]} speed={0.2} opacity={0.5} />
          <Cloud position={[4, 2, 0]} speed={0.2} opacity={0.75} />
        </group>
        <group position={[-10, 10, 5]}>
          <Cloud position={[-4, -2, -25]} speed={0.2} opacity={1} />
          <Cloud position={[4, 2, -15]} speed={0.2} opacity={0.5} />
          <Cloud position={[-4, 2, -10]} speed={0.2} opacity={1} />
          <Cloud position={[4, -2, -5]} speed={0.2} opacity={0.5} />
          <Cloud position={[4, 2, 0]} speed={0.2} opacity={0.75} />
        </group>
      </Suspense>
      <ambientLight intensity={0.01} />
      {/* <hemisphereLight intensity={0.125} color="#734036" groundColor="red" /> */}
      {/* <hemisphereLight intensity={0.125} color="#8040df" groundColor="red" /> */}
      {/* <spotLight castShadow color="orange" intensity={2} position={[-50, 50, 40]} angle={0.25} penumbra={1} shadow-mapSize={[128, 128]} shadow-bias={0.00005} /> */}
      <group scale={10}>
        {/* <spotLight
          castShadow
          color="orange"
          intensity={1}
          position={[50, 100, 0]}
          angle={0.15}
          penumbra={0.5}
          shadow-mapSize={[64, 64]}
          shadow-bias={-0.000001}
          target-position={[0, 20, 0]}
        /> */}
      </group>

      <Suspense fallback={null}>
        {/* <Bounds fit clip observe margin={1}> */}
        <group position={[0, 0, 0]}>
          {/* <group position={[5, 43, -12]}> */}

          <group scale={10}>
            {/* <spotLight
              castShadow
              color="orange"
              intensity={1}
              position={[50, 100, 0]}
              angle={0.15}
              penumbra={0.5}
              shadow-mapSize={[64, 64]}
              shadow-bias={-0.000001}
              target-position={[0, 20, 0]}
            /> */}
          </group>
          <group scale={1.7} position={[4 - 5, 20 - 5, -7]}>
            <ModelWall scale={1} position={[-8.8 * 3.5, 0, 8.8 * 2.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
            <ModelWall scale={1} position={[-8.8 * 3.5, 0, 8.8 * 1.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
            <ModelWall scale={1} position={[-8.8 * 3.5, 0, 8.8 * 0.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
            <ModelWall scale={1} position={[-8.8 * 3, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />

            <ModelWall scale={1} position={[-8.8 * 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
            <ModelWall scale={1} position={[-8.8, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
            <ModelWall scale={1} position={[0, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
            <ModelWall scale={1} position={[8.8, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
            <ModelWall scale={1} position={[8.8 * 2, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
            <ModelWall scale={1} position={[8.8 * 3, 0, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow />
            <ModelWall scale={1} position={[8.8 * 3.5, 0, 8.8 * 2.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
            <ModelWall scale={1} position={[8.8 * 3.5, 0, 8.8 * 1.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
            <ModelWall scale={1} position={[8.8 * 3.5, 0, 8.8 * 0.5]} rotation={[Math.PI / 2, 0, Math.PI / 2]} receiveShadow />
          </group>
          <group scale={1.5} position={[-2 - 5, 13.5, -3]}>
            {/* <ModelCupboard position={[-5, 0, 0]} receiveShadow /> */}
            <ModelCupboard scale={[-1, 1, 1]} position={[-26.5 + 2, 0, 0]} />
            <ModelCupboard scale={[-1, 1, 1]} position={[-14.5 + 2, 0, 0]} />
            <ModelCupboard position={[22.5 - 2, 0, 0]} />
            <ModelCupboard scale={[-1, 1, 1]} position={[34.5 - 2, 0, 0]} />
          </group>
          {/* <group scale={1.5} position={[-2 - 5, 13.5, -3]}>
              <ModelCupboard position={[-5, 0, 0]} receiveShadow />
              <ModelCupboard scale={[-1, 1, 1]} position={[7.1, 0, 0]} receiveShadow />
              <ModelCupboard position={[19.2, 0, 0]} receiveShadow />
            </group> */}

          <spotLight position={[5, 30, 30]} angle={0.5} penumbra={1} />
          <Bounds fit clip observe margin={1}>
            <SelectToZoom clicked_to_Left={clicked_to_Left} click_to_Left={click_to_Left} click_to_Right={click_to_Right} clicked_to_Right={clicked_to_Right}>
              <group dispose={null}>
                <ModelCMD
                  onClick={(event) => click_to_Left(!clicked_to_Left)}
                  position={[0, 21, 0]}
                  scale={3}
                  rotation={[-Math.PI / 2 + 0.5, -Math.PI / 2, 0]}
                />
                <ModelDraco scale={10} position={[5 - 6, 1.5 + 1, 1]} receiveShadow castShadow />
                <group position={[5 - 5, 43 + 2, -11]}>
                  <GoldenText scale={5} rotation={[0, Math.PI / 2, Math.PI / 2 + 0.1]} receiveShadow />
                </group>
              </group>
              <group>
                {/* <ModelCMD
                  onClick={(event) => click_to_Left(!clicked_to_Left)}
                  position={[-40, 21, 20]}
                  scale={3}
                  rotation={[-Math.PI / 2 + 0.5, -Math.PI / 2, 0]}
                /> */}
              </group>
            </SelectToZoom>
          </Bounds>
          <ContactShadows position={[0, 0, 0]} scale={[100, 40]} blur={10} far={20} receiveShadow castShadow />

          {/* <ModelDraco scale={10} position={[5 - 5, 1.5 + 1, 5.5 * 2]} receiveShadow /> */}
        </group>
        {/* </Bounds> */}
      </Suspense>
      <mesh scale={8.8 * (9 + 3)} rotation={[-Math.PI / 2, 0, 0]} position={[0, 0, 20]} castShadow receiveShadow>
        <planeGeometry />
        {/* <meshDepthMaterial color={'red'} /> */}
        <meshBasicMaterial receiveShadow attach="material" color="#994639" opacity={0.9} />
        {/* <meshLambertMaterial receiveShadow attach="material" color="#CB1B45" opacity={0.9} /> */}
        {/* <meshBasicMaterial attach="material" color="#64363C" opacity={0.9} /> */}
      </mesh>
      {/* <Bounds fit clip observe margin={1}> */}
      {/* <Room position={[0, 0, 15]} scale={[0.1, 0.19, 0.1]} /> */}
      {/* </Bounds> */}
      <BakeShadows />
      <OrbitControls
        ref={ref_zero}
        // position={clicked_to_Left ? [100, 10, 10] : [10, 10, 10]}
        makeDefault
        //clicked_to_Right, click_to_Right
        // minAzimuthAngle={clicked_to_Left ? -Math.PI / 16 + Math.PI / 2 : -Math.PI / 16}
        // maxAzimuthAngle={clicked_to_Left ? Math.PI / 16 + Math.PI / 2 : Math.PI / 16}
        minAzimuthAngle={clicked_to_Left && clicked_to_Right ? (clicked_to_Left ? -Math.PI / 16 + Math.PI / 2 : -Math.PI / 16 + -Math.PI / 2) : -Math.PI / 16}
        maxAzimuthAngle={clicked_to_Left && clicked_to_Right ? (clicked_to_Left ? Math.PI / 16 + Math.PI / 2 : Math.PI / 16 - Math.PI / 2) : Math.PI / 16}
        // maxAzimuthAngle={Math.PI / 6}
        minPolarAngle={Math.PI / 3}
        maxPolarAngle={Math.PI / 3}
        enableZoom={true}
        enablePan={true}
        zoomSpeed={0.3}
        // target={ref_zero}
      />
      {/* <OrbitControls
        makeDefault
        minAzimuthAngle={0}
        maxAzimuthAngle={Math.PI / 2}
        minPolarAngle={Math.PI / 3}
        maxPolarAngle={Math.PI / 3}
        enableZoom={true}
        enablePan={true}
        zoomSpeed={0.3}
      /> */}
      {/* <gridHelper args={[1000, 200, '#151515', '#020202']} position={[0, -4, 0]} /> */}
      {/* <mesh scale={200} rotation={[-Math.PI / 2, 0, 0]} position={[0, -4, 0]} receiveShadow>
        <planeGeometry />
        <shadowMaterial transparent opacity={0.3} />
      </mesh> */}
    </Canvas>
  )
}

// This component wraps children in a group with a click handler
// Clicking any object will refresh and fit bounds
function SelectToZoom({ children, ...Props }) {
  const api = useBounds()
  const ref = useRef()

  const [toLeft, setToLef] = useState(false)

  return (
    <group
      ref={ref}
      // onClick={(e) => (e.stopPropagation(), e.delta <= 2 && api.refresh(e.object).fit())}
      onClick={(e) => {
        e.stopPropagation()
        // console.log(e.delta)
        // console.log(ref_B.position)

        Props.clicked_to_Left ? api.refresh(ref.current.children[4]).fit() : api.refresh(ref.current.children[3]).fit()
        // e.delta <= 2 && api.refresh(ref.current.children[1].children[0]).fit()
        // console.log(e.object)
        // console.log(ref)
        // console.log(ref.current.children[1].children[0])
      }}
      onPointerMissed={(e) => e.button === 0 && api.refresh().fit()}>
      {children}
      <ModelCMD
        name="ModelCMD_A"
        onClick={(event) => {
          setToLef(!toLeft)
          Props.click_to_Left(false)
          Props.click_to_Right(false)
        }}
        position={[0, 22, 0]}
        scale={4}
        rotation={[-Math.PI / 2 + 0.5, -Math.PI / 2, 0]}
      />
      <group
        name="ModelCMD_B"
        onClick={(event) => {
          setToLef(!toLeft)
          Props.click_to_Left(!Props.clicked_to_Left)
        }}
        scale={1.5}
        position={[-50, 13.5, 6]}
        rotation={[0, Math.PI / 2, 0]}>
        {/* <ModelCupboard position={[-5, 0, 0]} receiveShadow /> */}
        <ModelCupboard scale={[-1, 1, 1]} position={[-16.5, 0, 0]} />
        <ModelCupboard scale={[-1, 1, 1]} position={[-4.5, 0, 0]} />
      </group>
      <group
        name="ModelCMD_C"
        onClick={(event) => {
          setToLef(!toLeft)
          Props.click_to_Right(!Props.clicked_to_Right)
        }}
        scale={1.5}
        position={[50, 13.5, 40]}
        rotation={[0, -Math.PI / 2, 0]}>
        <ModelCupboard scale={[-1, 1, 1]} position={[-16.5, 0, 0]} />
        <ModelCupboard scale={[-1, 1, 1]} position={[-4.5, 0, 0]} />
      </group>
      {/* <ModelCMD
        name="ModelCMD_B"
        ref={ref_B}
        onClick={(event) => {
          setToLef(!toLeft)
          Props.click_to_Left(!Props.clicked_to_Left)
        }}
        position={[-40, 21, 20]}
        scale={4}
        rotation={[-Math.PI / 2 + 0.5, -Math.PI / 2, 0]}
      /> */}
    </group>
  )
}


上一篇
[Day 貳拾貳] 來開發元宇宙中藥鋪吧10 - 蒸氣騰騰
下一篇
[Day 貳拾五] 來開發元宇宙中藥鋪吧14 - 建立測試空間
系列文
當 APP develop 遇上 web3 與 Metaverse 浪潮 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言